/*
 * fftwPlane.cpp
 *
 *  Created on: Apr 4, 2012
 *      Author: snirgaz
 */

// fftw Plan
#include "fftwPlane.h"
#include <numeric>

fftwPlanMulti::fftwPlanMulti() {
	init_ = false;
}
fftwPlanMulti::~fftwPlanMulti() {
	if (init_)
		fftw_destroy_plan(plan_);
}
void fftwPlanMulti::execute() {
	fftw_execute(plan_);
}
void fftwPlanMulti::init(double *source, std::complex<double> *target, int rank,
		int * size, int repeat) {
	int dist = std::accumulate(size, size + rank, 1., std::multiplies<int>());
	int stride = 1; /* array is contiguous in memory */
	plan_ = fftw_plan_many_dft_r2c(rank, size, repeat, source, NULL, stride,
			dist, reinterpret_cast<fftw_complex*>(target), NULL, stride, dist,
			FFTW_MEASURE);
	init_ = true;
}
fftwPlan::fftwPlan() {
	init_ = false;
}
fftwPlan::~fftwPlan() {
	if (init_)
		fftw_destroy_plan(plan_);
}
void fftwPlan::execute() {
	fftw_execute(plan_);
}
void fftwPlan::executeNewArray(double *source, std::complex<double> *target) {
	fftw_execute_dft_r2c(plan_, source,
			reinterpret_cast<fftw_complex*>(target));
}
void fftwPlan::init(double *source, std::complex<double> *target, int rank,
		int * size) {
	plan_ = fftw_plan_dft_r2c(rank, size, source,
			reinterpret_cast<fftw_complex*>(target), FFTW_MEASURE);
	init_ = true;
}
// MKL
fftMKL::fftMKL() {
	init_ = false;
	hand_ = 0;
}
fftMKL::~fftMKL() {
	if (init_)
		DftiFreeDescriptor(&hand_);
}
void fftMKL::execute(double *source, std::complex<double> *target) {
	DftiComputeForward(hand_, source, target);
}
void fftMKL::init(int size) {
	DftiCreateDescriptor(&(hand_), DFTI_DOUBLE, DFTI_REAL, 1, (MKL_LONG)size);
	DftiSetValue(hand_, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
	DftiSetValue(hand_, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
	DftiCommitDescriptor(hand_);
	init_ = true;
}
